import java.time.DayOfWeek;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class BadmintonCourt {

    private String name;
    private ChargeStandard charge;
    private CourtOccupation occupation;
    private List<RevenueEntry> revenueEntryList;
    private int sumRevenue = 0;

    public BadmintonCourt(String name) {
        this.name = name;
        this.revenueEntryList = new LinkedList<>();
    }

    public String getName() {
        return name;
    }

    public int getSumRevenue() {
        return sumRevenue;
    }

    public void setCharge(ChargeStandard cs) {
        this.charge = cs;
    }

    public void setOccupation(CourtOccupation co) {
        this.occupation = co;
    }

    public boolean handleCustomerAction(CustomerAction ca) {
        if (ca.isCancel())
            return this.handleCancelAction(ca);

        return this.handleBookAction(ca);
    }

    public boolean handleBookAction(CustomerAction ca) {
        DayOfWeek day = ca.getBookDate().getDayOfWeek();
        int start = ca.getBeginTime().getHour();
        int end = ca.getEndTime().getHour();

        try {
            boolean flag = this.occupation.checkOccupied(day.getValue(), start, end);
            if (flag) {
                System.out.println("> Error: the booking conflicts with existing bookings!");
                return false;
            }

            int money = this.charge.calculateChargeMoney(day, start, end);
            this.occupation.setOccupied(day.getValue(), start, end);
            this.sumRevenue += money;

            RevenueEntry revenueEntry = new RevenueEntry(ca, false, money);
            this.revenueEntryList.add(revenueEntry);
        } catch (Exception e) {
            System.out.println("> Error: the booking time is out of range!");
            return false;
        }

        return true;
    }

    public RevenueEntry findBookReceiptInfo(CustomerAction ca) {
        for (RevenueEntry re : this.revenueEntryList) {
            if (re.infoEqual(ca))
                return re;
        }

        return null;
    }

    public boolean handleCancelAction(CustomerAction ca) {
        RevenueEntry bookre = this.findBookReceiptInfo(ca);

        if (bookre == null) {
            System.out.println("> Error: the booking being cancelled does not exist!");
            return false;
        }

        DayOfWeek day = ca.getBookDate().getDayOfWeek();
        int start = ca.getBeginTime().getHour();
        int end = ca.getEndTime().getHour();

        int money = bookre.getIncome();
        int penalty = this.charge.calculatePenaltyMoney(day, money);

        this.sumRevenue -= money;
        this.occupation.clearOccupied(day.getValue(), start, end);
        this.sumRevenue += penalty;

        this.revenueEntryList.remove(bookre);
        RevenueEntry newre = new RevenueEntry(ca, true, penalty);
        this.revenueEntryList.add(newre);

        return true;
    }

    public void printCourtReceipt() {
        System.out.println("> 场地:" + this.getName());

        Collections.sort(this.revenueEntryList);
        for (RevenueEntry re : this.revenueEntryList)
            System.out.println(re);

        System.out.println("> 小计：" + this.sumRevenue);
    }
}